/* Author ywl
* Description:
1.列表展示组件
2.slot: headerLeft =>表格顶部左侧信息;controlsBtn => 为表格列表操作列插槽
3.dicType: 列表配置动态字典类型值
4.dicProp: 列表配置动态字典的枚举字段
5.filter: 列表配置固定枚举对象
6.colOptionEnum: 动态枚举字典选项集合
7.handlerClick: 列表表格内点击事件
8.isSelection: 是否展示列表多选框 默认true
9.isClearSelection: 是否在列表数据刷新时清除勾选状态 默认true
10.isMarClass: 是否展示列表顶部信息或者按钮
11.isShowTooltip: 是否在鼠标悬浮时展示信息
12.cell-click: 单元格点击事件
*/
<template>
  <div :class="['myTable']">
    <el-table ref="tableRef" style="width: 100%;" :data="getTable" size="small" :current-row-key="id"
      :empty-text="emptyText" row-class-name="row" tooltip-effect="dark" :highlight-current-row="true" fit border
      row-key="id" :default-expand-all="isSelection" :tree-props="{ children: 'childNodeList' }"
      @selection-change="handleSelectionChange" @cell-click="handlerClick">
      <el-table-column v-if="isSelection" class="selection" type="selection" :reserve-selection="true" align="center"
        width="45" />
      <el-table-column align="center" type="index" label="序号" width="50" />
      <el-table-column v-for="(item, index) in columns" :key="index" align="center" :prop="item.prop"
        :width="item.width" :label="item.label">
        <template slot-scope="scope">
          <template v-if="!item.check">
            <el-tooltip :content="backTooltip(scope.row[item.prop])" :disabled="item.edit">
              <el-input v-if="finishShowEdit(item, scope, editFlag) && scope.row.id === editIndex"
                v-model="scope.row[item.prop]" class="pms-wz-input el-table-inline" size="mini"
                @change="changeInput(scope.row, item)" @blur="removeClass" />
              <span v-else class="header-tooltip" :style="{ 'background': showColor(item, scope) }">{{
                scope.row[item.prop] }}</span>
            </el-tooltip>
          </template>
          <el-checkbox v-else :value="scope.row[item.prop] === 1" disabled />
        </template>
        <el-table-column v-for="(childrens, _index) in item.children" :key="_index" align="center"
          :prop="childrens.prop" :width="childrens.width" :label="childrens.label">
          <template slot-scope="scope">
            <el-tooltip :content="backTooltip(scope.row[childrens.prop])" :disabled="!childrens.edit">
              <el-input v-if="finishShowEdit(childrens, scope, editChildrenFlag) && scope.row.id === editIndex"
                v-model="scope.row[childrens.prop]" class="pms-wz-input el-table-inline" size="mini"
                @change="changeInput(scope.row, childrens)" @blur="removeClass" />
              <span class="header-tooltip" :style="{ 'background': showColor(childrens, scope) }">{{
                scope.row[childrens.prop] }}</span>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table-column>
      <slot name="controlsBtn" />
    </el-table>
  </div>
</template>

<script>
import store from '@/store'
import { subEditor } from '../configOption'
import { handleEdit } from './handelEdit'
export default {
  name: 'MyTable',
  // 因为是子组件，要接受父组件传递的数据，所以这里我们定义props
  props: {
    // 返回数据id
    id: {
      type: [String, Number],
      required: true,
      default: ''
    },
    // 父组件传递过来的表格数据
    tableData: {
      type: Array,
      default: () => []
    },
    // 父组件传递过来的表头数据
    columns: {
      type: Array,
      default: () => []
    },
    // 父组件传递过来的操作按钮数据
    tableOperation: {
      type: Array,
      default: () => []
    },
    // 列表数据枚举字段选项集
    colOptionEnum: {
      type: Object,
      default: () => ({})
    },
    // 是否展示列表多选框 默认true
    isSelection: {
      type: Boolean,
      default: false
    },
    // 是否展示列表顶部信息或者按钮
    isMarClass: {
      type: Boolean,
      default: false
    },
    // 是否在列表数据刷新时清除勾选状态 默认true
    isClearSelection: {
      type: Boolean,
      default: true
    },
    // 暂无数据提示
    emptyText: {
      type: String,
      default: '暂无数据'
    },
    workDetail: {
      type: Object,
      default: () => ({})
    },
    basicPrjDetail: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      eventName: 'click', // 点击按钮绑定的方法，这样写法也可以去绑定一些其他的比如change等方法
      multipleSelection: [], // 这个数组用来保存被选择行的数据，顺序是按照你勾选的顺序来排序的
      temporary: '', // 上次保存的单元格数据
      editIndex: '-1', // 是否可以编辑单元格index
      editFlag: false,
      editChildrenFlag: false,
      clcikProp: '',
      subEditor,
      saveValue: ''// 保存单元格数据
    }
  },
  computed: {
    getTable() {
      this.tableData.forEach(item => {
        if (!item.id) {
          if (item.childNodeList) {
            item.childNodeList.forEach(i => {
              i['id'] = this.generateRandomId()
            })
          }
          item['id'] = this.generateRandomId()
        }
      })
      return this.tableData
    },
  },
  watch: {
    // 监听表格数据是否发生改变并清空
    tableData: {
      handler(newVal) {
        if (newVal.length && this.isClearSelection) {
          this.$refs.tableRef.clearSelection()
        }
      },
      deep: true
    }
  },
  methods: {
    backTooltip(row) {
      return row !== null ? row?.toString() : ''
    },
    // 随机数
    generateRandomId(length = 8) {
      const chars = '0123456789'
      let result = ''
      const arr = new Uint8Array(length)
      window.crypto.getRandomValues(arr)
      for (let i = 0; i < length; i++) {
        // 注意：Uint8Array中的值范围是0-255，所以我们需要将其转换为字符集的有效索引
        const idx = arr[i] % chars.length
        result += chars[idx]
      }
      return result
    },
    // 是否可以编辑
    finishShowEdit(item, scope, flag) {
      return item.edit && this.shouledEdit(scope.row, item) && flag && item.prop === this.clcikProp
    },
    // 列表表格颜色
    showColor(item, scope) {
      return item.edit && this.shouledEdit(scope.row, item) ? 'rgb(255, 250, 238)' : ''
    },
    /**
     * 
     * @param row 当前行数据
     * @param item  表头 item.prop
     */
    // 是否可以编辑每个单元格逻辑
    shouledEdit(row, item) {
      if ((this.$route.query.type === 'todo' && this.workDetail.activityDefID === 'reduce2_cs01') || this.$route.query.status === 'todo') {
        return handleEdit(row, item, this.$route.query.status, this.basicPrjDetail.fieldProjectManager)
      }
      return false
    },
    // @selection-change方法可以监听到表格里哪一行被选中，类型是数组;
    // 然后我们将它赋值给定义好的 multipleSelection
    handleSelectionChange(rowList) {
      this.multipleSelection = rowList
      this.$emit('handleSelection', rowList)
      store.commit('settings/setTableCheckData', rowList)
    },
    // 清空选中
    clearSelection() {
      this.$refs.tableRef.clearSelection()
    },
    // 列表表格点击事件
    async handlerClick(row, prop, cell, event) {
      this.saveValue = row[prop.property]
      //点击的哪一个编辑
      const _cellStatus = this.columns.some(item => {
        if (!item.children) {
          return item.prop === prop.property && item.edit
        }
        return item.children.some(children => children.prop === prop.property && children.edit)
      })

      if (!_cellStatus) {
        return
      }
      for (let i = 0; i < document.getElementsByClassName('current-cell').length; i++) {
        document.getElementsByClassName('current-cell')[i].classList.remove('current-cell');
      }
      cell.classList.add("current-cell");
      // 当前点击的编辑
      this.clcikProp = prop.property
      this.editIndex = row.id
      // 符合二级表格编辑
      if (this.subEditor.includes(prop.property)) {
        this.editChildrenFlag = this.shouledEdit(row, prop)
        this.editFlag = false;
      } else {
        this.editFlag = this.shouledEdit(row, prop)
        this.editChildrenFlag = false;
      }
    },
    isMobileBasic(phone) {
      if (phone === "") {
        return true
      }
      return /^(?=^.{1,14}$)(?:\d{1,4})?\d{11}$/.test(phone) && phone.length <= 14;
    },
    // input框填完成以后的回调
    changeInput(row, item) {
      // 精度限制
      if (isNaN(row[item.prop]) && !['keeperContact', 'keeper', 'keeperAddress'].includes(item.prop)) {
        row[item.prop] = this.saveValue;
        this.$message.warning(('非法字符'))
      }
      // 电话
      if (item.prop === 'keeperContact' && !(this.isMobileBasic(row[item.prop]))) {
        row[item.prop] = ''
        this.$message.warning(('保管人电话输入有误,请重新输入!'))
        return
      }
      this.$emit('changeInput', row, item, this.saveValue)
    },
    removeClass() {
      this.editFlag = false
      this.clcikProp = ""
      document.getElementsByClassName('current-cell')[0].classList.remove('current-cell');
    }
  },
  mounted() {
    this.$nextTick(() => {
      const _dom = this.$refs.tableRef.$el;
      const _emptyText = _dom.querySelector('.el-table__empty-block');
      if (_emptyText !== null) {
        _emptyText.style.width = '100%';
      }
    })
  }
}
</script>

<style lang="scss" scoped>
.myTable .el-input {
  display: none;
}

.current-cell .el-input {
  display: block;
}

.current-cell .el-input+span {
  display: none;
}

.slotContent {
  // flex: 1;
  width: 100%;
}

::v-deep .pms-button-primary {
  color: #fff;
}



.header-tooltip {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
  min-height: 24px;
  padding: 0 6px;
}

::v-deep .el-table__row .el-table__expand-column .cell:hover {
  background: none;
}


::v-deep .el-form-item .el-form-item__content {
  width: auto;
  color: #606266;
  font-size: 12px;
}

::v-deep .el-form-item__label {
  width: 140px;
  text-align: left;
  margin-left: 53px;
  line-height: 25px;
}

::v-deep .el-table__fixed-right {
  height: 100% !important; //设置高优先，以覆盖内联样式
}

::v-deep .el-table__fixed {
  height: 100% !important; //设置高优先，以覆盖内联样式
}

::v-deep .el-table thead .is-group th.el-table__cell:nth-last-child(2) {
  color: black !important;
}

::v-deep .el-input__inner {
  height: 22px !important;
  font-size: 12px !important;
  box-sizing: border-box;
  text-align: center;
}

::v-deep .el-table .cell {
  padding-left: 0;
  padding-right: 0;
}

::v-deep .el-table__row td:nth-child(1) .cell {
  padding-left: 0px;
}
</style>
